#define _CRT_SECURE_NO_WARNINGS 1

////指针数组
//#include<stdio.h>
//int main()
//{
//	int a = 10, b = 20, c = 30;
//	int* arr[] = { &a,&b,&c };
//	for (int i = 0;i < 3;i++)
//	{
//		printf("%d\n", *arr[i]);
//	}
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//	int a[] = { 1,2,3,4,5,6 };
//	int b[] = { 1,9,8,7,6,5 };
//	int c[] = { 0,3,0,8,2,3 };
//	int* arr[] = { a,b,c };
//	for (int i = 0;i < 3;i++)
//	{
//		for (int j = 0;j < 6;j++)
//		{
//			//printf("%d ", *(arr[i] + j));
//			printf("%d ", arr[i][j]);//[j]转化为+j解引用
//		}
//		printf("\n");
//	}
//	return 0;
//}

//#include <stdio.h>
//int main()
//{
//	int arr[10] = { 0 };
//	printf("%p\n", arr);
//	printf("%p\n", arr + 1);
//
//	printf("%p\n", &arr);
//	printf("%p\n", &arr + 1);
//	return 0;
//}

//#include <stdio.h>
//void print_arr1(int arr[3][5], int row, int col)
//{
//    for (int i = 0; i < row; i++)
//    {
//        for (int j = 0; j < col; j++)
//        {
//            printf("%d ", arr[i][j]);
//        }
//        printf("\n");
//    }
//}
//void print_arr2(int(*arr)[5], int row, int col)
//{
//    for (int i = 0; i < row; i++)
//    {
//        for (int j = 0; j < col; j++)
//        {
//            //printf("%d ", *(*(arr + i) + j));//arr+i,跳过i个数组
//            printf("%d ", arr[i][j]);
//        }
//        printf("\n");
//    }
//}
//int main()
//{
//    int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
//    print_arr1(arr, 3, 5);
//    //数组名arr，表示首元素的地址
//    //但是二维数组的首元素是二维数组的第一行
//    //所以这里传递的arr，其实相当于第一行的地址，是一维数组的地址
//    //可以数组指针来接收
//    print_arr2(arr, 3, 5);
//    return 0;
//}

//函数指针
//#include<stdio.h>
//int add(int a,int b)
//{
//	return a + b;
//}
//int main()
//{
//	int a = 0, b = 0;
//	scanf("%d %d", &a, &b);
//	int (*p)(int, int) = &add;
//    //int (*p)(int, int) = add;//也行所以p==add
//	int ret = (*p)(a, b);//这样写只是更容易理解
//	//int ret = add(a, b);
//	//int ret = p(a, b);//所以这样写也行
//	//要加*要括起来，加多少都可以
//	printf("%d\n", ret);
//	return 0;
//}

//代码1
//(*(void (*)())0)();
//void (*)();//是函数指针
//*(void (*)());//括起来解引用就是二级指针
//
////代码2
//void (*signal(int, void(*)(int)))(int);
////整体是函数指针，函数类型是void，参数类型是int
//(int, void(*)(int))//是变量？
//void(*)(int);//函数指针
//代码1
//(*(void (*)())0)();
////代码2
//void (*signal(int, void(*)(int)))(int);
////解析：
//int main()
//{
//	(*(void (*)())0)();
//	//()0 把0强制类型转换
//    //void (*)()是函数指针
//	(void (*)())0;//把0强制类型转化为函数指针类型
//	(*(void (*)())0);//解引用最后加()调用函数
//	//(*(void (*)())0)();所以这是调用0地址处的函数，该函数无参，返回类型是void
//
//	void (*signal(int, void(*)(int)))(int);
//	//按优先级signal和()结合，所以signal是函数名
//	//signal(int, void(*)(int))是函数名和函数类型，
//	//第一个类型是int 第二个类型是函数指针
//	//一个函数，函数名和函数类型讨论了，剩下是就是函数返回类型
//	//void (*)(int)就是函数的返回类型，为函数指针
//	//void (*signal(int, void(*)(int)))(int);所以这是一个函数的声明
//	//如果可以写成void (*)(int) signal(int, void(*)(int))就容易理解，但语法不支持
//	//但语法支持的太复杂，如何简化：
//	//对void (*)(int)重命名成pfun_t 
//	//但语法又不能写成typedef void (*)(int) pfun_t
//	//所以写成以下格式
//	typedef void(*pfun_t)(int);
//	pfun_t signal(int, pfun_t);
//	return 0;
//}

//#include <stdio.h>
//int add(int a, int b)
//{
//    return a + b;
//}
//int sub(int a, int b)
//{
//    return a - b;
//}
//int mul(int a, int b)
//{
//    return a * b;
//}
//int div(int a, int b)
//{
//    return a / b;
//}
//int main()
//{
//    int x = 0, y = 0;
//    int input = 1;
//    int ret = 0;
//    do
//    {
//        printf("*******************************\n");
//        printf("*****  1:add       2:sub  *****\n");
//        printf("*****  3:mul       4:div  *****\n");
//        printf("*****        0:exit       *****\n");
//        printf("*******************************\n");
//        printf("请选择：");
//        scanf("%d", &input);
//        switch (input)
//        {
//        case 1:
//            printf("输入操作数：");
//            scanf("%d %d", &x, &y);
//            ret = add(x, y);
//            printf("ret = %d\n", ret);
//            break;
//        case 2:
//            printf("输入操作数：");
//            scanf("%d %d", &x, &y);
//            ret = sub(x, y);
//            printf("ret = %d\n", ret);
//            break;
//        case 3:
//            printf("输入操作数：");
//            scanf("%d %d", &x, &y);
//            ret = mul(x, y);
//            printf("ret = %d\n", ret);
//            break;
//        case 4:
//            printf("输入操作数：");
//            scanf("%d %d", &x, &y);
//            ret = div(x, y);
//            printf("ret = %d\n", ret);
//            break;
//        case 0:
//            printf("退出程序\n");
//            break;
//        default:
//            printf("选择错误\n");
//            break;
//        }
//    } while (input);
//    return 0;
//}
//#include <stdio.h>
//void menu()
//{
//	printf("*******************************\n");
//	printf("*****  1:add       2:sub  *****\n");
//	printf("*****  3:mul       4:div  *****\n");
//	printf("*****        0:exit       *****\n");
//	printf("*******************************\n");
//}
//int add(int a, int b)
//{
//	return a + b;
//}
//int sub(int a, int b)
//{
//	return a - b;
//}
//int mul(int a, int b)
//{
//	return a * b;
//}
//int div(int a, int b)
//{
//	return a / b;
//}
//int main()
//{
//	int x = 0, y = 0;
//	int input = 1;
//	int ret = 0;
//	int(*p[5])(int x, int y) = { NULL, add, sub, mul, div }; //转移表 《C和指针》
//	do
//	{
//		menu();
//		printf("请选择：");
//		scanf("%d", &input);
//		if ((input <= 4 && input >= 1))
//		{
//			printf("输入操作数：");
//			scanf("%d %d", &x, &y);
//			ret = (*p[input])(x, y);
//			printf("ret = %d\n", ret);
//		}
//		else if (input == 0)
//		{
//			printf("退出程序");
//		}
//		else
//		{
//			printf("选择错误，重新选择\n");
//		}
//	} while (input);
//	return 0;
//}

//#include<stdio.h>
//#include<stdlib.h>//qsort的头文件
////qsort函数的使用者得实现一个比较函数
//int int_cmp(const void* p1, const void* p2)
//{
//    return (*(int*)p1 - *(int*)p2);
//}
//int main()
//{
//    int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
//    qsort(arr, sizeof(arr) / sizeof(arr[0]), sizeof(int), int_cmp);
//    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
//    {
//        printf("%d ", arr[i]);
//    }
//    printf("\n");
//    return 0;
//}


//#include <stdio.h>
//#include <stdlib.h>
//#include <string.h>
//
//struct Stu
//{
//    char name[20];
//    int age;
//};
//
//int cmp_struct_age(const void* p1, const void* p2)
//{
//    return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
//}
//
//int cmp_struct_name(const void* p1, const void* p2)
//{
//    return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
//}
//
//void struct_sort()
//{
//    // 使用qsort函数排序结构体数据
//    struct Stu s[3] = {
//        {"zhangsan", 20},
//        {"lisi", 40},
//        {"wangwu", 30}
//    };
//    int sz = sizeof(s) / sizeof(s[0]);
//    // 按照年龄排序
//    //qsort(s, sz, sizeof(s[0]), cmp_struct_age);
//    // 按照名字来排序
//    qsort(s, sz, sizeof(s[0]), cmp_struct_name);
//}
//
//int main()
//{
//    struct_sort();
//    return 0;
//}

//#include <stdio.h>
//#include <string.h>
//
//struct Stu
//{
//    char name[20];
//    char age;
//};
//
//// 模仿qsort实现一个冒泡排序的通用算法
//void Swap(char* buf1, char* buf2, int width) 
//{
//    int i = 0;
//    for (i = 0; i < width; i++) 
//    {
//        //一个字节一个字节交换
//        char tmp = *buf1;
//        *buf1 = *buf2;
//        *buf2 = tmp;
//        buf1++;
//        buf2++;
//    }
//}
//
//void bubble_sort_q(
//    void* base, // 首元素地址
//    int sz, // 元素总个数
//    int width, // 每个元素的大小
//    int (*cmp)(const void* p1, const void* p2) // 两个元素的函数
//)
//{
//    // 确认趟数
//    int i = 0;
//    for (i = 0; i < sz - 1; i++) 
//    {
//        // 一趟排序
//        int j = 0;
//        for (j = 0; j < sz - 1 - i; j++) {
//            // 两个元素比较   arr[i] arr[j+i]
//            if (cmp((char*)base + j * width, (char*)base + (j + 1) * width) > 0) 
//            {
//                //传参给用户传进来的cmp函数，但不知道比较的数据的类型
//                //把base强制类型转化为char*，一个字节一个字节交换
//                //把两个元素的地址传给cmp函数，升序，>0就交换
//                Swap((char*)base + j * width, (char*)base + (j + 1) * width, width);
//            }
//        }
//    }
//}
//
//int cmp_struct_age(const void* p1, const void* p2) 
//{
//    return ((struct Stu*)p1)->age - ((struct Stu*)p2)->age;
//}
//int cmp_struct_name(const void* p1, const void* p2)
//{
//    return strcmp(((struct Stu*)p1)->name, ((struct Stu*)p2)->name);
//}
//void struct_sort()
//{
//     //使用qsort排序结构体数据
//        struct Stu s[3] = {
//        {"zhangsan", 20},
//        {"lisi", 40},
//        {"wangwu", 30}
//        };
//    int sz = sizeof(s) / sizeof(s[0]);
//    // 按照年龄排序
//    bubble_sort_q(s, sz, sizeof(s[0]), cmp_struct_age);
//    // 按照名字排序
//    bubble_sort_q(s, sz, sizeof(s[0]), cmp_struct_name);
//}
//
//void print_arr(int arr[], int sz)
//{
//    int i = 0;
//    for (i = 0; i < sz; i++) 
//    {
//        printf("%d ", arr[i]);
//    }
//    printf("\n");
//}
//
//int cmp_int(const void* p1, const void* p2) 
//{
//    // 升序： p1 - p2
//    return *(int*)p1 - *(int*)p2;
//}
//void int_sort()
//{
//    int arr[] = { 0,1 ,2,3,6,5,4,8,7,9 };
//    int sz = sizeof(arr) / sizeof(arr[0]);
//    // 排序
//    bubble_sort_q(arr, sz, sizeof(arr[0]), cmp_int);
//    // 打印
//    print_arr(arr, sz);
//}
//
//int main()
//{
//    int_sort();
//    // struct_sort();
//    return 0;
//}

//一维数组
////数组名的意义：
////1. sizeof(数组名)，这里的数组名表示整个数组，计算的是整个数组的大小。
////2. & 数组名，这里的数组名表示整个数组，取出的是整个数组的地址。
////3. 除此之外所有的数组名都表示首元素的地址。
//#include<stdio.h>
//int main()
//{
//	int a[] = { 1,2,3,4 };
//	printf("%d\n", sizeof(a));//16
//	printf("%d\n", sizeof(a + 0));//4/8 第一个元素的地址
//	printf("%d\n", sizeof(*a));//4   第一个元素的大小
//	printf("%d\n", sizeof(a + 1));//4/8   第二个元素的地址
//	printf("%d\n", sizeof(a[1]));//4    第二个元素的大小
//
//	printf("%d\n", sizeof(&a));//4/8  整个数组的地址
//	printf("%d\n", sizeof(*&a));//16  整个数组的大小(取地址解引用相当于最上面的printf)
//	printf("%d\n", sizeof(&a + 1));//4/8  跳过a数组的下个空间的地址
//	printf("%d\n", sizeof(&a[0]));//4/8   第一个元素的地址
//	printf("%d\n", sizeof(&a[0] + 1));//4/8  第二个元素的地址
//	return 0;
//}

//字符数组

//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	char arr[] = { 'a','b','c','d','e','f' };
//	printf("%d\n", sizeof(arr));//6
//	printf("%d\n", sizeof(arr + 0));//4/8  第一个元素的地址
//	printf("%d\n", sizeof(*arr));//1   第一个元素的大小
//	printf("%d\n", sizeof(arr[1]));//1
//	printf("%d\n", sizeof(&arr));//4/8
//	printf("%d\n", sizeof(&arr + 1));//4/8
//	printf("%d\n", sizeof(&arr[0] + 1));//4/8
//
//	printf("%d\n", strlen(arr));//随机数（没有\0）
//	printf("%d\n", strlen(arr + 0));//上面的随机数（没有\0）
//	printf("%d\n", strlen(*arr));//（把97当做地址）错误
//	printf("%d\n", strlen(arr[1]));//错误
//	printf("%d\n", strlen(&arr));//上面的随机数（没有\0）
//	printf("%d\n", strlen(&arr + 1));//上面的随机数-6（没有\0）
//	printf("%d\n", strlen(&arr[0] + 1));//上面的随机数-1（没有\0）
//	return 0;
//}

//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	char arr[] = "abcdef";
//	printf("%d\n", sizeof(arr));//7          (加上\0)!!!
//	printf("%d\n", sizeof(arr + 0));//4/8
//	printf("%d\n", sizeof(*arr));//1
//	printf("%d\n", sizeof(arr[1]));//1
//	printf("%d\n", sizeof(&arr));//4/8
//	printf("%d\n", sizeof(&arr + 1));//4/8
//	printf("%d\n", sizeof(&arr[0] + 1));//4/8
//
//	printf("%d\n", strlen(arr));//6
//	printf("%d\n", strlen(arr + 0));//6
//	printf("%d\n", strlen(*arr));//错误emm
//	printf("%d\n", strlen(arr[1]));//错误emm
//	printf("%d\n", strlen(&arr));//6
//	printf("%d\n", strlen(&arr + 1));//随机数
//	printf("%d\n", strlen(&arr[0] + 1));//5
//	return 0;
//}

//#include<stdio.h>
//#include<string.h>
//int main()
//{
//	char* p = "abcdef";
//	printf("%d\n", sizeof(p));//4/8  指针的大小
//	printf("%d\n", sizeof(p + 1));//4/8  第二个元素的地址!
//	printf("%d\n", sizeof(*p));//1    第一个元素的大小!
//	printf("%d\n", sizeof(p[0]));//1  同上emm
//	printf("%d\n", sizeof(&p));//4/8
//	printf("%d\n", sizeof(&p + 1));//4/8
//	printf("%d\n", sizeof(&p[0] + 1));//4/8
//
//	printf("%d\n", strlen(p));//6
//	printf("%d\n", strlen(p + 1));//5
//	//printf("%d\n", strlen(*p));//错误
//	//printf("%d\n", strlen(p[0]));//错误
//	printf("%d\n", strlen(&p));//随机数  从p的地址算，p里面存的地址！！
//	printf("%d\n", strlen(&p + 1));//和上面不同的随机数
//	printf("%d\n", strlen(&p[0] + 1));//5
//	return 0;
//}

//#include<stdio.h>
//int main()
//{
//    int a[3][4] = { 0 };
//    printf("%d\n", sizeof(a));//12*4=48   整个数组大小
//    printf("%d\n", sizeof(a[0][0]));//4   第一个元素大小
//    printf("%d\n", sizeof(a[0]));//16   下一a[0]不是单独放在内部，不表示第一行
//    printf("%d\n", sizeof(a[0] + 1));//4/8  a[0]是整形的地址，+1跳过一个整形emm
//    printf("%d\n", sizeof(*(a[0] + 1)));//4  第一行第二个元素的大小
//    printf("%d\n", sizeof(a + 1));//4/8    第二行的地址
//    printf("%d\n", sizeof(*(a + 1)));//16   第二行大小  相当于a[1]
//    printf("%d\n", sizeof(&a[0] + 1));//4/8   第二行地址
//    printf("%d\n", sizeof(*(&a[0] + 1)));//16   第二行大小   同上上 
//    printf("%d\n", sizeof(*a));//16     第一行大小等价于*(a+0)等价于a[0]     
//    printf("%d\n", sizeof(a[3]));//16    3+5  1.值属性：8   2.类型属性：int
//    //a[3]  值属性越界了，但是类型属性是int [4]  编译器推算的，不会真正取地址emm  
//                                           //且sizeof内部是不进行计算的
//    return 0;
//}

//#include<stdio.h>
//int main()
//{
//	int a[5] = { 1, 2, 3, 4, 5 };
//	int* ptr = (int*)(&a + 1);  //整个数组地址+1跳过一个数组  本来的类型是int*[5]
//	printf("%d,%d", *(a + 1), *(ptr - 1));//2,5  都是整形指针，只能跳过4个字节emm
//	return 0;
//}
//程序的结果是什么？

//#include<stdio.h>
////由于还没学习结构体，这里告知结构体的大小是20个字节
//struct Test
//{
//	int Num;
//	char* pcName;
//	short sDate;
//	char cha[2];
//	short sBa[4];
//}*p;
////假设p 的值为0x100000。 如下表表达式的值分别为多少？
////已知，结构体Test类型的变量大小是20个字节
//int main()
//{
//	printf("%p\n", p + 0x1);//+16进制的1，就是1  这个结构体指针+1跳过20字节
//	                        //0x100000变成0x100014    (16进制14就是10进制的20)
//	printf("%p\n", (unsigned long)p + 0x1); //整形+1就是+1   0x100001
//	printf("%p\n", (unsigned int*)p + 0x1);//跳过4个字节   0x100004
//	return 0;
//}

//笔试题3
//#include<stdio.h>
//int main()
//{
//	int a[4] = { 1, 2, 3, 4 };
//	int* ptr1 = (int*)(&a + 1);   //跳过一个数组
//	int* ptr2 = (int*)((int)a + 1);   //a的地址转化为int +1
//	                                 //一个地址给一个字节，差一个字节
//	printf("%x,%x", ptr1[-1], *ptr2);  //ptrl[-1]==*(ptr1-1)==4
//	return 0;
//}
////结果是4,2000000    看图


////笔试题4
//#include <stdio.h>
//int main()
//{
//	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
//	//()不是{}   是逗号表达式！  1  3
//	//                           5  0
//	//                           0  0
//	int* p;
//	p = a[0];
//	printf("%d", p[0]);//p==a[0]   p[0]==a[0][0]==1
//	return 0;
//}

//笔试题5
//#include<stdio.h>
//int main()
//{
//	int a[5][5];
//	int(*p)[4];
//	p = a;
//	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);
//	return 0;
//}
////a的类型是int(*)[5]   p的类型是int(*)[4]
////答案是FFFFFFFC,-4    看图

////笔试题6
//#include<stdio.h>
//int main()
//{
//	int aa[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//	int* ptr1 = (int*)(&aa + 1); //&aa整个数组的地址+1跳过整个数组
//	int* ptr2 = (int*)(*(aa + 1));//首元素（首元素是第一行）地址+1，第二行地址
//	//第二行首元素地址解引用得到6  int*没有意义，本来就是   *(aa + 1)相当于aa[1]
//	printf("%d,%d", *(ptr1 - 1), *(ptr2 - 1));//指针-1：10,5 
//	return 0;
//}

////笔试题7：
//#include <stdio.h>
//int main()
//{
//	char* a[] = { "work","at","alibaba" };//指针数组
//	char** pa = a;
//	pa++;//跳过数组里的一个元素，跳到at的地址
//	printf("%s\n", *pa);//at
//	return 0;
//}

//笔试题8
//#include <stdio.h>
//int main()
//{
//	char* c[] = { "ENTER","NEW","POINT","FIRST" };
//	char** cp[] = { c + 3,c + 2,c + 1,c };
//	char*** cpp = cp;
//	printf("%s\n", **++cpp);//++cpp==c+2 解引用得c+2内容，即POINT地址 再解引用得POINT
//	printf("%s\n", *-- * ++cpp + 3);//++cpp在上一行基础在+1得到c+1地址
//	//解引用得c+1内容 再--得到c的内容 再解引用得到ENTER的地址即E的地址 
//	//再+3得到第二个E的地址  打印出ER
//	printf("%s\n", *cpp[-2] + 3);//*cpp[-2]==*(*(cpp-2))
//	//cpp在上面内容-2得到c+3的内容  解引用得到c+3地址 再解引用得到FIRST地址
//	//再+3得到S的地址  打印出ST
//	printf("%s\n", cpp[-1][-1] + 1);//cpp[-1][-1]==*(*(cpp-1)-1)
//	//++cpp等价于cpp=cpp+1  cpp变了 但cpp-2 cpp没有变 还是指向c+1
//	//cpp在上面内容-1得到c+2的内容  解引用得到c+2地址 再-1得到c+1的地址
//	//再解引用得到NEW的地址  再+1得到E的地址  打印出EW
//	return 0;
//}

//#include <stdio.h>
//void print_arr(int* arr, int row, int col)
//{
//	printf("1");
//}
//int main()
//{
//	int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 };
//	print_arr(arr, 3, 5);
//	return 0;
//}

//杨氏矩阵
//#include <stdio.h>
//void find_int_arr(int arr[3][3], int r, int c, int k)
//{
//    //右上角元素：
//    int x = 0;
//    int y = c - 1;//列-1，（下标）
//
//    while (y >= 0 && x <= r - 1)
//    {
//        //找一次：
//        if (arr[x][y] < k)
//        {
//            x++;
//        }
//        else if (arr[x][y] > k)
//        {
//            y--;
//        }
//        else
//        {
//            printf("找到了，下标是:x=%d y=%d\n", x, y);
//            return;
//        }
//    }
//    printf("找不到\n");
//}
//
//int main()
//{
//    int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
//    //  1   2   3
//    //  4   5   6
//    //  7   8   9
//    //若要找的元素是k＝2，比右上角的3小，因为3是一列中最小的元素，所以去掉一列；
//    //    若要找的元素是k＝7，比右上角的3大，因为3是一行中最大的元素，
//    //    所以去掉一行；7比在剩下的元素中右上角的6还要大，则又去掉一行；
//    //    7与剩下元素中右上角的9小，则在这一行中查找7，
//    //    （因为9已经是剩下元素所在列中最小的元素）去掉一列；
//    //    8比7大说明还在8的左边，去掉一列；7与7相等则找到；
//    //    如果7还找不到则结果就是找不到。
//
//    int k = 0;
//    scanf("%d", &k);
//    find_int_arr(arr, 3, 3, k);//传arr和行、列、要找的元素
//
//    return 0;
//}


//#include <stdio.h>
//void find_int_arr(int arr[3][3], int* px, int* py, int k)
//{
//    int x = 0;
//    int y = *py - 1;//*py就是3
//
//    while (y >= 0 && x <= *px - 1)//*px就是3
//    {
//        if (arr[x][y] < k)
//        {
//            x++;
//        }
//        else if (arr[x][y] > k)
//        {
//            y--;
//        }
//        else
//        {
//            //printf("找到了，下标是:x=%d y=%d\n", x, y);
//            *px = x;
//            *py = y;
//            return;
//        }
//    }
//    /*printf("找不到\n");*/
//    //数组中合理的坐标不可能是-1和-1
//    *px = -1;
//    *py = -1;
//}
//
//int main()
//{
//    int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
//
//    int k = 0;
//
//    //函数中会用到:
//    int x = 3;
//    int y = 3;
//
//    scanf("%d", &k);
//    find_int_arr(arr, &x, &y, k);
//    //传x和y的地址，则在函数中所求的下标就可以通过这两个地址放到x、y中
//
//    //函数返回后判断：
//    if (x == -1 && y == -1)
//    {
//        printf("找不到\n");
//    }
//    else
//    {
//        printf("找到了，下标是：%d %d\n", x, y);
//    }
//
//    return 0;
//}
////这里传& x和& y的好处：
////既可以带进函数两个值：3和3，在函数中使用；
////又可以在函数结束的时候带回值——这种设计是返回型参数（输出型参数），
////用指针修改，把数值带回去。


#include<stdio.h>
int find_arr(int arr[3][3], int* row, int* col, int k)
{
    int x = 0, y = *col - 1;//从右上角开始找
    while (x < *row && y >= 0)
    {
        if (arr[x][y] > k)
        {
            y--;
        }
        else if (arr[x][y] < k)
        {
            x++;
        }
        else
        {
            *row = x;
            *col = y;
            return 1;
        }
    }
    return 0;
}
int main()
{
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };
    int k = 0, x = 3, y = 3;
	scanf("%d", &k);
    //找到返回1 找不到返回0
    //传arr和行、列、要找的元素
    //传行和列的地址，则在函数中所求的下标就可以通过这两个地址放到x、y中
    if (find_arr(arr, &x, &y, k))
	{
		printf("找到了,下标是%d,%d\n",x,y);
        
	}
	else
	{
		printf("找不到\n");
	}
	return 0;
}